package com.ruoyi.aitcommon.utils;

import java.lang.reflect.Method;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.quartz.util.JobInvokeUtil;

@Component
public class BeanUtils {
//	@Autowired
//	private ServiceDefineConfig flowServiceConfig;
//	private static ServiceDefineConfig staticFlowServiceConfig;
	
	@PostConstruct
	public void init() throws Exception {
//		通过该方式在静态方法中调用spring容器bean
//		staticFlowServiceConfig=flowServiceConfig;
	}
	
	public static String getBeanName(String invokeTarget) {
		return JobInvokeUtil.getBeanName(invokeTarget);
	}
	public static String getMethodName(String invokeTarget) {
		return JobInvokeUtil.getMethodName(invokeTarget);
	}
	
	public static String[] getMethodParamsName(String invokeTarget)
    {
        String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")");
        if (StringUtils.isEmpty(methodStr)){
            return new String[]{};
        }
        String[] methodParams = methodStr.split(",");
        return methodParams;
    }
	
	//通过配置文件获取参数类型
//	public static Class<?>[] getMethodParamsType(String beanName,String methodName) throws Exception {
//		
//		List<String> types = staticFlowServiceConfig.getMethodType(beanName, methodName);
//		if(types==null||types.size()==0) {
//			throw new Exception("服务["+beanName+"."+methodName+"]未找到定义！");
//		}
//		Class<?>[] classs = new Class<?>[types.size()];
//        int index = 0;
//        for (String item : types)
//        {
//            classs[index] = Class.forName(item);
//            index++;
//        }
//        return classs;
//	}
	
	//通过bean反射获取参数类型
	public static Class<?>[] getMethodParamsType(Object bean,String methodName) throws Exception {
		Method[] methods = bean.getClass().getDeclaredMethods();
		for(Method method:methods) {
			if(method.getName().equals(methodName)) {
				return method.getParameterTypes();
			}
		}
		
		String msg="[%s]不存在方法[%s]!";
		msg=String.format(msg, bean.getClass().getSimpleName(),methodName);
		throw new Exception(msg);
	}

	/**
     * 执行方法
     * <pre>
     * 举例：
     * ryTask.ryNoParams
     * ryTask.ryParams('ry')
     * ryTask.ryMultipleParams('ry', true, 2000L, 316.50D, 100)
     * 支持类型:
     * 	'ry':字符串
     * 	true:布尔
     * 	2000L:长整型
     * 	316.50D:Double型
     * 	100:整形
     * 	'${sqldata.sql1}':变量
     * </pre>
     * @param invokeTarget 方法名称,比如:demoService.hello1()
     * @param pmap 上下文
     * @return 目标方法的返回值
     */
	public static Object invokeMethod(String invokeTarget,Map<String,Object> pmap)
			throws Exception
    {
        String beanName = getBeanName(invokeTarget);
        Object bean=null;
//        获取bean对象
        if (!JobInvokeUtil.isValidClassName(beanName)){
            bean = SpringUtils.getBean(beanName);
        }
        else{
            bean = Class.forName(beanName).newInstance();
        }
//      获取bean的方法名,参数类型,参名称,参数值
        String methodName = getMethodName(invokeTarget);
//        Class<?>[] methodParamsType = getMethodParamsType(beanName,methodName);
        Class<?>[] methodParamsType = getMethodParamsType(bean,methodName);
        String[] names = getMethodParamsName(invokeTarget);
        if(methodParamsType.length!=names.length)
        	throw new Exception(invokeTarget+"参数配置与传入参数不一致");
        Object[] methodParamsValue = FlowParamUtils.getMehtodParamsValue(pmap,names);
        
//        调用方法
        return invokeMethod(bean, methodName,methodParamsType,methodParamsValue);
    }
	
	/**
     * 调用任务方法
     *
     * @param bean 目标对象
     * @param methodName 方法名称
     * @param methodTypes 参数类型
	 * @param methodValues 参数值
     */
    public static Object invokeMethod(Object bean, String methodName
    		, Class<?>[] methodTypes,Object[] methodValues)
            throws Exception
    {
    	Object ret=null;
    	try {
	        if (StringUtils.isNotNull(methodTypes) && methodTypes.length > 0)
	        {
//	        	带参数调用
	            Method method = bean.getClass().getDeclaredMethod(methodName, methodTypes);
	            ret=method.invoke(bean, methodValues);
	        }
	        else
	        {
//	        	无参数调用
	            Method method = bean.getClass().getDeclaredMethod(methodName);
	            ret=method.invoke(bean);
	        }
	        return ret;
    	}catch(Exception ex) {
    		String msg="调用方法失败,bean:%s,method:%s";
    		msg=String.format(msg, bean.getClass().getName(),methodName);
//    		在AitFlowAspect打印异常
//    		ex.printStackTrace();
//    		if(ex.getCause()!=null)
//    			throw new Exception(msg,ex.getCause());
//    		else
//    			throw new Exception(msg,ex);
    		throw new Exception(msg,ex);
    	}
    }
    
    
}
